import fs from 'fs-extra';
import path from 'path';
import { VueComponent } from '../../core/types';
import { CacheManager } from '../cache/CacheManager';
import { FileUtils } from '../utils/FileUtils';

/**
 * 组件扫描信息
 */
export interface ComponentScanInfo {
  // 文件路径
  filePath: string;
  // 组件名称
  name: string;
  // 组件功能名称
  functionName?: string;
}

/**
 * Vue组件解析器基类
 */
export abstract class BaseComponentParser {
  // 缓存管理器
  protected cacheManager: CacheManager;
  // 扫描路径
  protected scanPaths: string[];
  // 最后更新时间
  protected lastUpdateTime: string = new Date().toISOString();
  // 已扫描的组件基本信息
  protected scannedComponents: ComponentScanInfo[] = [];

  /**
   * 构造函数
   * @param scanPaths 要扫描的组件路径数组
   */
  constructor(scanPaths: string[]) {
    this.scanPaths = scanPaths;
    this.cacheManager = new CacheManager();
    
    console.log(`初始化组件解析器，扫描路径: ${scanPaths.join(', ')}`);
  }

  /**
   * 启动文件监视
   */
  public startWatcher(): void {
    this.cacheManager.startWatcher(this.scanPaths, (filePath) => this.handleFileChange(filePath));
  }

  /**
   * 停止文件监视
   */
  public stopWatcher(): void {
    this.cacheManager.stopWatcher();
  }

  /**
   * 处理文件变化
   * @param filePath 文件路径
   */
  protected async handleFileChange(filePath: string): Promise<void> {
    try {
      // 检查文件是否存在
      const exists = await FileUtils.fileExists(filePath);
      
      if (!exists) {
        // 如果文件不存在，移除缓存
        this.cacheManager.removeComponent(filePath);
        console.log(`已从缓存中删除组件: ${filePath}`);
      } else {
        // 解析组件并更新缓存
        const component = await this.parseComponent(filePath);
        if (component) {
          this.cacheManager.setComponent(filePath, component);
          console.log(`已更新组件缓存: ${component.name} (${filePath})`);
        }
      }
      
      this.lastUpdateTime = new Date().toISOString();
    } catch (error) {
      console.error(`处理文件变化时出错 ${filePath}:`, error);
    }
  }

  /**
   * 查找组件文件
   * @param scanPath 扫描路径
   * @returns 组件文件路径数组
   */
  protected async findComponentFiles(scanPath: string): Promise<string[]> {
    const absolutePath = FileUtils.getAbsolutePath(scanPath);
    
    // 检查路径是否存在
    const pathExists = await FileUtils.fileExists(absolutePath);
    
    if (!pathExists) {
      console.warn(`路径不存在: ${absolutePath}`);
      return [];
    }
    
    // 将 Windows 路径转换为使用正斜杠的格式
    const normalizedPath = FileUtils.normalizePath(absolutePath);
    // 使用正斜杠构建模式
    const pattern = `${normalizedPath}/**/*.vue`;
    
    try {
      return await FileUtils.findFiles(pattern);
    } catch (error) {
      console.error(`查找组件文件失败: ${error}`);
      return [];
    }
  }

  /**
   * 生成组件ID
   * @param filePath 文件路径
   * @returns 组件ID
   */
  protected generateComponentId(filePath: string): string {
    // 获取相对于项目根目录的路径
    const relativePath = FileUtils.getRelativePath(filePath);
    // 将路径转换为ID格式
    return relativePath.replace(/[\\/]/g, '-').replace(/\.vue$/, '');
  }

  /**
   * 解析单个组件
   * @param filePath 组件文件路径
   * @returns 解析后的组件信息
   */
  protected abstract parseComponent(filePath: string): Promise<VueComponent | null>;

  /**
   * 解析所有组件
   */
  public async parseComponents(): Promise<void> {
    try {
      // 首先扫描所有组件文件
      await this.scanComponents();
      
      // 清空缓存，重新解析所有组件
      this.cacheManager.clearCache();

      console.log(`开始解析 ${this.scannedComponents.length} 个组件...`);
      
      for (const componentInfo of this.scannedComponents) {
        try {
          // 检查缓存中是否已存在该组件
          if (!this.cacheManager.hasComponent(componentInfo.filePath)) {
            const component = await this.parseComponent(componentInfo.filePath);
            if (component) {
              this.cacheManager.setComponent(componentInfo.filePath, component);
            }
          }
        } catch (error) {
          console.error(`解析组件 ${componentInfo.filePath} 时出错:`, error);
        }
      }
      
      this.lastUpdateTime = new Date().toISOString();
      console.log(`组件解析完成，共解析 ${this.cacheManager.getComponentCount()} 个组件`);
    } catch (error) {
      console.error(`解析组件时出错:`, error);
    }
  }

  /**
   * 扫描所有组件的基本信息
   */
  public async scanComponents(): Promise<void> {
    this.scannedComponents = [];
    
    for (const scanPath of this.scanPaths) {
      console.log(`扫描路径: ${scanPath} 中的组件`);
      const componentFiles = await this.findComponentFiles(scanPath);
      console.log(`在路径 ${scanPath} 中找到 ${componentFiles.length} 个组件文件`);
      
      for (const filePath of componentFiles) {
        // 初始化组件基本信息，组件名默认为文件名
        const name = path.basename(filePath, '.vue');
        
        this.scannedComponents.push({
          filePath,
          name,
        });
      }
    }
    
    console.log(`扫描完成，共找到 ${this.scannedComponents.length} 个组件`);
  }

  /**
   * 检查文件是否在扫描路径内
   * @param filePath 文件路径
   * @returns 是否在扫描路径内
   */
  public isFileInScanPaths(filePath: string): boolean {
    const absoluteFilePath = FileUtils.getAbsolutePath(filePath);
    
    for (const scanPath of this.scanPaths) {
      const absoluteScanPath = FileUtils.getAbsolutePath(scanPath);
      
      if (absoluteFilePath.startsWith(absoluteScanPath)) {
        return true;
      }
    }
    
    return false;
  }

  /**
   * 获取组件列表
   * @returns 组件列表
   */
  public getComponentList(): VueComponent[] {
    return this.cacheManager.getAllComponents();
  }

  /**
   * 根据ID获取组件
   * @param id 组件ID
   * @returns 组件信息
   */
  public getComponentById(id: string): VueComponent | undefined {
    return this.cacheManager.getComponentById(id);
  }

  /**
   * 获取最后更新时间
   * @returns 最后更新时间
   */
  public getLastUpdateTime(): string {
    return this.lastUpdateTime;
  }
} 